﻿using Ivory;
using Microsoft.Xna.Framework;
using DefCore.Tools;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Input;
using DefCore.Interfaces;

namespace DefCore.Core
{
    public sealed class SelectionEngine
    {
        private static SelectionEngine _Instance;
        public static SelectionEngine Instance
        {
            get
            {
                if (_Instance == null)
                    _Instance = new SelectionEngine();

                return _Instance;
            }
        }
        
        //Fields
        public List<ISelectable> Selectables { get; private set; }

        public event EventHandler<SelectableChangedEventArgs> SelectionChanged;
        public event EventHandler<SelectionClickEventArgs> SelectionClick;

        public ISelectable CurrentlySelected { get; private set; }
        public ISelectable CurrentlyHovered { get; private set; }
        
        //ctor
        protected SelectionEngine()
        {
            this.Selectables = new List<ISelectable>();
        }

        //Methods
        public void ClearSelection()
        {
            if (CurrentlySelected == null)
                return;

            CurrentlySelected.IsSelected = false;
            CurrentlySelected = null;
        }
        public void Update(LevelBase baseLevel, InputControl input, GameTime time)
        {
            Point mousePosition = input.MousePoint;
            IEnumerable<ISelectable> hovered = Selectables.Where(s => s.IsHoverTarget);
            if (hovered != null)
                hovered.ToList().ForEach(f => f.IsHoverTarget = false);

            if (input.IsKeyDown(Keys.Escape))
                ClearSelection();

            Point translatedMousePoint = mousePosition;// new Point((int)(mousePosition.X + ObjectHolder.GameCamera.CameraTopLeft.X), (int)(mousePosition.Y + ObjectHolder.GameCamera.CameraTopLeft.Y));
            ISelectable hit = Selectables.Where(s => s.HitBox.Contains(translatedMousePoint)).OrderBy(x => x.HitIndex).LastOrDefault();
            if (hit != null)
            {
                //Somthing has been hit!
                //take the last item, This will be the highest on the HitIndex, and check it.
                hit.IsHoverTarget = true;
                CurrentlyHovered = hit;

                //Send a message saying the hover target has changed
                if (SelectionChanged != null)
                    SelectionChanged(this, new SelectableChangedEventArgs(hit, false));

                if (input.IsLeftClick())
                {
                    if (CurrentlySelected != null)
                    {
                        //There is somthing Selected.
                        if (CurrentlySelected == hit)
                        {
                            //We selected the same thing
                            ClearSelection();
                        }
                        else if (hit.IsSelectable)
                        {
                            //We want to select somthing new, unselect old, select new
                            ClearSelection();
                            CurrentlySelected = hit;
                            CurrentlySelected.IsSelected = true;

                            //Send a message saying the Selection target has changed
                            if (SelectionChanged != null)
                                SelectionChanged(this, new SelectableChangedEventArgs(hit, true));
                        }
                        else
                        {
                            //Its not selectable, we clicked somewhere the game is interested in, so raise an event
                            if (SelectionClick != null)
                                SelectionClick(this, new SelectionClickEventArgs(new DungeonPos(input.MouseVect), hit));
                        }
                    }
                    else
                    {
                        if (hit.IsSelectable)
                        {
                            //Thing we clicked on becomes selected
                            CurrentlySelected = hit;
                            CurrentlySelected.IsSelected = true;

                            //Send a message saying the Selection target has changed
                            if (SelectionChanged != null)
                                SelectionChanged(this, new SelectableChangedEventArgs(hit, true));
                        }
                        else
                        {
                            //we clicked somewhere the game is interested in, so raise an event
                            if (SelectionClick != null)
                                SelectionClick(this, new SelectionClickEventArgs(new DungeonPos(input.MouseVect), hit));
                        }
                    }
                }
            }
        }

    }
}
